header {
package com.hermeneute.fsa.parser;
}

{
import com.hermeneute.fsa.*;
import com.hermeneute.fsa.editors.FSTReader;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.resources.IResource;

import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;

import java.util.*;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.StringReader;
import java.util.Hashtable;
import antlr.CharScanner;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IFile;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.File;
}
class FSTParser extends Parser;

options {
    k=6; // needed for newline junk
    defaultErrorHandler = false;
}

{
	IProject project;
	IPath path;
	IProgressMonitor monitor;
	FSTOperator op = new FSTOperator();
	Hashtable amem = new Hashtable();
	Hashtable camem = new Hashtable();
	FSTResult res;
	int line = 0;
	public void setPM(IProgressMonitor m){
		monitor = m;
	}
	public void setProject(IProject p){
		project = p;
	}
	public void setPath(IPath p){
		path = p;
	}
}
//file throws Exception : statement{System.out.print("> ");} (statement{System.out.print("> ");})*;
file throws Exception : 
	statement {
		monitor.worked(1);
		if(monitor.isCanceled())throw new OperationCanceledException();
		}
	(statement{
		monitor.worked(1);
		if(monitor.isCanceled())throw new OperationCanceledException();
		})*;

statement  throws Exception 
{FSTAutomaton x;}
	: y1:SYMBOL EQ (
		x=expression{
			//System.out.println("Adding "+y1.getText());
			amem.put(y1.getText(),x);
		}
        | READ y2:STRING{
			String sfin = (String)y2.getText();
			//System.out.println(project.findMember(sfout).getFullPath().toOSString());
			IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
			System.out.println(path);
			System.out.println(path.append(sfin));
			IResource ifin = root.getFile(path.append(sfin));
			File fin = ifin.getLocation().toFile();
		
        	x=new FSTAutomaton(); 
        	x.read(ifin.getLocation().toString());
        	amem.put(y1.getText(),x);
        }) SC
    | WRITE  x=expression TO y3:STRING
    	{	
			String sfout = (String)y3.getText();
			//System.out.println(project.findMember(sfout).getFullPath().toOSString());
			IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
			System.out.println(path);
			System.out.println(path.append(sfout));
			IResource ifout = root.getFile(path.append(sfout));
			File fout = ifout.getLocation().toFile();
			BufferedWriter out = new BufferedWriter(new FileWriter(fout));
			try{x.write(out);ifout.refreshLocal(IResource.DEPTH_ONE, null);}
			catch(Exception fstx){throw new RecognitionException (fstx.getMessage()+", "+y3.getText());
			
	    		
    		}
    	} SC
	| PRINT   x=expression
		{
			try{x.print();}
			catch(Exception fstx){throw new RecognitionException (fstx.getMessage()+", print");}
		} SC
	| DISPLAY y4:STRING{System.out.println(y4.getText());} SC
	| INSERT y5:STRING 
		INTO x=expression{x.trieInsertStr((String)y5.getText());} SC
	| OPTIMIZE s:SYMBOL{
		x=(FSTAutomaton)amem.get(s.getText());
		x=op.optimize(x);
		amem.put(s.getText(),x);
	} SC
	| a1:AUTOMATON EQ COMPILE  s1:SYMBOL{
		FSTSequentialTransducer st = new FSTSequentialTransducer((FSTAutomaton)amem.get(s1.getText()));
		camem.put(a1.getText(),st);
	} SC
	| PARSE a2:AUTOMATON FILE y6:STRING{
		try {
			
			FSTSequentialTransducer st = (FSTSequentialTransducer)camem.get(a2.getText());
			if (st != null) {
				FSTReader fr = new FSTReader(st,new FileReader(y6.getText()));
				BufferedReader br = new BufferedReader(fr);
				
			    try { 
					String input; 
					while ((input = br.readLine()) != null) { 
					    System.out.println(input); 
					    System.out.flush(); 
					} 
					br.close();
				} catch (Exception e) { 
					System.err.println("Tagger run: " + e); 
			    } 
			} else {
				System.out.println("No Automaton found");    		
			}
			System.out.println();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	} SC
	| PARSE a3:AUTOMATON y7:STRING{
		try {
			FSTSequentialTransducer st = (FSTSequentialTransducer)camem.get(a3.getText());
			if (st != null) {
				FSTReader fr = new FSTReader(st,new StringReader(y7.getText()));
				BufferedReader br = new BufferedReader(fr);
				
			    try { 
					String input; 
					while ((input = br.readLine()) != null) { 
					    System.out.println(input); 
					    System.out.flush(); 
					} 
					br.close(); 
				} catch (Exception e) { 
					System.err.println("Tagger run: " + e); 
			    } 
			} else {
				System.out.println("No Automaton found");    		
			}
			System.out.println();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}  SC
	| SL_COMMENTS WS
	;

expression returns [FSTAutomaton a = null] throws Exception 
	: a=intersectionExpression
	;

intersectionExpression returns [FSTAutomaton a = null]	 throws Exception 
{FSTAutomaton x;}
	: a=unionExpression (AND x=unionExpression{a=op.computeIntersection(a,x);})*
	;

unionExpression	returns [FSTAutomaton a = null]	  throws Exception 
{FSTAutomaton x;}
	: a=productExpression (UNION x=productExpression{a=op.computeUnion(a,x);})*
	;

productExpression returns [FSTAutomaton a = null]    throws Exception 
{FSTAutomaton x;}
	: a=subExpression (x=subExpression{a=op.computeConc(new FSTAutomaton(a),x);})*
	;


subExpression returns [FSTAutomaton a = null]	 throws Exception 
	: a=atomicExpression   (PLUS{FSTAutomaton tmp =new FSTAutomaton(a); a=op.computeStar(a);a=op.computeConc(tmp,a);} | 
				QUESTION{a=op.computeQuestion(a);} | 
				STAR{a=op.computeStar(a);})?
	| a=parenthesisExpression(PLUS{FSTAutomaton tmp =new FSTAutomaton(a); a=op.computeStar(a);a=op.computeConc(tmp,a);} | 
				QUESTION{a=op.computeQuestion(a);} | 
				STAR{a=op.computeStar(a);})?
	;

parenthesisExpression returns [FSTAutomaton a = null]  throws Exception 
	: LPAR a=expression  RPAR
	| NOT LPAR a=expression {a=op.computeNot(a);} RPAR
	;


			
atomicExpression returns [FSTAutomaton a = null]  throws Exception 	
	: a=atomicExpressionU
	| a=atomicExpressionP
	| a=var
	;

setExp returns [String a = null]  throws Exception 
	: LSET x:STRING{a=x.getText();} RSET 
	;



var returns [FSTAutomaton a = null]  throws Exception 
	: x:SYMBOL{a=(FSTAutomaton)amem.get((String)x.getText());if (a == null){ a = new FSTAutomaton();amem.put((String)x.getText(),a);}}
	;

string returns [String a = null]  throws Exception 
	: x:STRING {a=x.getText();}
	;

atomicExpressionU returns [FSTAutomaton a = null]  throws Exception 
{String x;}
	: ANY{a = new FSTAutomaton();a.anyAny();}
	| ZERO COL x=string{a = new FSTAutomaton();a.epsilonStr(x);}
	;


atomicExpressionP returns [FSTAutomaton a = null]  throws Exception 
{String x;String y;}
	: x=string{a = new FSTAutomaton();a.strId(x);}  
	  (COL ZERO{a = new FSTAutomaton();a.epsilonStr(x);})?  
	;

class FSTLexer extends Lexer;

options {
    k=4; // needed for newline junk
    charVocabulary='\u0000'..'\uFFFF'; // allow ascii
}
COMPILE
	: "compile"
	;

PARSE
	: "parse"
	;

FILE
	: "file"
	;

INSERT
	: "insert"
	;

INTO
	: "into"
	;

TO
	: ">>"
	;

READ
	: "read"
	;

PRINT
	: "print"
	;

WRITE
	: "write"
	;

LT
	: '<'
	;

GT
	: '>'
	;

SC
	: ';'
	;

EQ
	: '='
	;

PLUS
	: '+'
	;

QUESTION
	: '?'
	;

STAR
	: '*'
	;

NOT
	: '^'
	;

LPAR
	: '('
	;

RPAR
	: ')'
	;

LSET
	: '['
	;

RSET
	: ']'
	;

PERC
	: '%'
	;

UNION
	: '|'
	;

AND
	: '&'
	;

COL
	: ':'
	;

ANY	
	: '@'
	;

ZERO
	: '0'
	;

SYMBOL
	: '<' (('a' .. 'z')|('A' .. 'Z')| '_')(('a' .. 'z')|('A' .. 'Z')| ('0' .. '9') | '_')* '>' 
	;

AUTOMATON
	: '[' (('a' .. 'z')|('A' .. 'Z')| '_')(('a' .. 'z')|('A' .. 'Z')| ('0' .. '9') | '_')* ']' 
	;


	// Whitespace -- ignored
WS	:	(	' '
		|	'\t'
		|	'\f'
				// handle newlines
		|	(	options {generateAmbigWarnings=false;}
				:	"\r\n"  // Evil DOS
				|	'\r'    // Macintosh
				|	'\n'    // Unix (the right way)
				)
				{ newline(); }
		)+
		{ _ttype = Token.SKIP; }
	;

STRING
	: '"'! ( ESCAPE | ~('"'|'\\') )* '"'! 
	;


SL_COMMENT
	:	"#"
		(~('\n'|'\r'))* ('\n'|'\r'('\n')?)
		{$setType(Token.SKIP); newline();}
	;

protected
ESCAPE
    :    '\\'
         ( 'n' { $setText("\n"); }
         | 'r' { $setText("\r"); }
         | 't' { $setText("\t"); }
         | '"' { $setText("\""); }
         | '\\' { $setText("\\"); }
         )
    ;




